在 React 16 之前的架構是 Stack Reconciler,過程是同步進行的。當進行大量更新(例如渲染大量資料或進行複雜操作)時,更新無法中斷,直到整個渲染過程完成。這會導致畫面卡頓,讓使用者無法順暢和網頁互動,造成不良的使用者體驗。
React fiber 是 React 16 推出的 reconciliation 架構。透過 React Fiber 可以達成以下兩個功能:
總共會分成兩個階段:
Fiber 是 React 將工作拆解為小單位後的基本單位。具體來說,React 首先會將 JSX 轉換為 React Elements (透過 React.createElement
),接著這些 Elements 會被轉換成 Fiber Node。
每個 Fiber Node 都是一個 JavaScript 物件,包含許多重要的屬性,以下是一些關鍵屬性的簡介:
key
:用來辨識每個 fiber 的唯一值elementType
: JSX 中對應的元素類型stateNode
: 指向當前 Fiber 節點所對應的真實 DOM 節點return
: 指向當前 Fiber 節點的父節點child
: 指向當前 Fiber 節點的第一個子節點sibling
: 指向當前 Fiber 節點的下一個兄弟節點flags
:用來標記當前節點的狀態,描述這個節點需要做哪些更新操作subtreeFlags
:用來標記子節點樹的狀態,描述子節點需要做的操作lanes
:標記當前 Fiber 節點在更新過程中的優先級。更詳細的屬性內容可以參考此 原始碼。
透過 fiber Node 的屬性(child
, sibling
, index
)的關係可以組成 fiber tree,會是一個 linked list 的結構。
React 的渲染過程涉及兩顆 Fiber 樹:
在 Render Phase 中,React 會遍歷 workInProgressTree 的節點,根據 flags
和 subtreeFlags
來記錄各節點需要進行的更新操作。當 Render Phase 完成後會進入 Commit Phase,在此階段會更改 DOM,並觸發 lifecycle hooks(如 useEffect 和 useLayoutEffect)。
React 預設的渲染模式是同步的。在 React 18 引入了 Concurrent Mode 和相關的 Hooks。透過這些 Hooks 用來決定哪些功能可以設為可中斷和非緊急的,像是 startTransition
, useTransition
, useDeferredValue
和 Suspense
。
瀏覽器的每個重繪 (repaint) 之間,React 會檢查是否有緊急的更新,如果有,則中斷當前渲染,優先處理緊急更新。
參考資料和圖片來源:
https://legacy.reactjs.org/docs/codebase-overview.html
https://www.youtube.com/watch?v=ZCuYPiUIONs
https://medium.com/starbugs/react-%E9%96%8B%E7%99%BC%E8%80%85%E4%B8%80%E5%AE%9A%E8%A6%81%E7%9F%A5%E9%81%93%E7%9A%84%E5%BA%95%E5%B1%A4%E6%9E%B6%E6%A7%8B-react-fiber-c3ccd3b047a1
https://medium.com/@jettycloud/react-fiber-concurrency-part-1-b9d287077d1b
https://medium.com/@jettycloud/react-fiber-concurrency-part-2-5e32e4dac96